package util;

import java.util.Iterator;
import java.util.List;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Predicate;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * 对象列表生成器
 * 支持元素数量限制，和函数式校验限制
 * @Author Antony
 * @Since 2017/12/12 15:53
 */
public class Generator<E> implements Iterator<E> {

    private long count;
    private E nextValue;
    private Long size;
    private UnaryOperator<E> function;  //对象生成式
    private Predicate<E> predicate;     //对象校验式

    private Iterator<E> iterator;



    public static Generator getGenerator(Iterator it){
       return new Generator(it);
    }

    /**
     * 指定迭代器作为生成器
     * @param it
     */
    private Generator(Iterator it){
        this.iterator = it;
    }

    /**
     * 指定初始值和生成函数，无限列表
     * @param nextValue
     * @param function
     */
    public Generator(E nextValue, UnaryOperator<E> function) {
        this.nextValue = nextValue;
        this.function = function;
    }

    /**
     * 指定生成器元素数量
     * @param nextValue 初始值
     * @param function  生成器函数
     * @param size      数量
     */
    public Generator(E nextValue, UnaryOperator<E> function, Long size) {
        this.nextValue = nextValue;
        this.size = size;
        this.function = function;
    }

    /**
     * 指定判定结尾元素的函数
     * @param nextValue 初始值
     * @param function  生成器函数
     * @param predicate 校验式函数
     */
    public Generator(E nextValue, UnaryOperator<E> function, Predicate<E> predicate) {
        this.nextValue = nextValue;
        this.function = function;
        this.predicate = predicate;
    }

    @Override
    public boolean hasNext() {
        if(iterator != null){
            return iterator.hasNext();
        }
        if(size != null){
            return count < size;
        }
        if(predicate != null){
            return predicate.test(nextValue);
        }
        return true;
    }

    @Override
    public E next() {
        if(iterator != null){
            return iterator.next();
        }
        if(!hasNext()){
            throw new IllegalArgumentException("generator has no next value");
        }
        E result = nextValue;
        nextValue = getNextValue();
        count++;
        return result;
    }

    /**
     * 获取当前对象的Stream
     * @return
     */
    public Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }

    /**
     * 获取当前对象流，参数表示是否并行
     * @param parallel
     * @return
     */
    public Stream<E> stream(boolean parallel) {
        return StreamSupport.stream(spliterator(), parallel);
    }


    public List<E> toList(){
        return null;
    }


    /**
     * 返回迭代下一个元素的值
     * @return
     */
    private E getNextValue(){
        return function.apply(nextValue);
    }

    /**
     * 获取当前对象的Spliterator
     * @return
     */
    private Spliterator<E> spliterator(){
        if(size != null){
            return Spliterators.spliterator(this, size, 0);
        }
        return Spliterators.spliteratorUnknownSize(this, 0);
    }
}
